﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using ParallelMath.Library;
using ParallelMath.Library.AbstractDependencies;
using ParallelMath.Tests.Helpers;

namespace ParallelMath.Tests
{
    [TestClass]
    public class MatrixOperationsTests
    {
        [TestMethod]
        public void TestGenerateNew2DMatrixInRange()
        {
            double[,] generateRandom = MatrixOperations2D.GenerateRandom2DMatrix(1000,500,2,5);
            generateRandom.AllItemsAreInRange(2, 5);
            Assert.AreEqual(1000, generateRandom.GetLength(0));
            Assert.AreEqual(500, generateRandom.GetLength(1));
        }

        

        [TestMethod]
        public void TestAddNormal()
        {
            double[,] matrix1 = MatrixOperations2D.GenerateRandom2DMatrix(1, 15, 0, 100);
            double[,] matrix2 = MatrixOperations2D.GenerateRandom2DMatrix(1, 15, 0, 100);
            double[,] ints = matrix1.Add(matrix2);

            double[,] matrixRes = matrix1.Add(matrix2,true);

            CollectionAssert.AreEqual(matrixRes,ints);
        }

        [TestMethod]
        public void TestAddNormal2()
        {
            double[,] matrix1 = MatrixOperations2D.GenerateRandom2DMatrix(3, 4, 0, 100);
            double[,] matrix2 = MatrixOperations2D.GenerateRandom2DMatrix(3, 4, 0, 100);
            double[,] ints = matrix1.Add(matrix2);

            double[,] matrixRes = matrix1.Add(matrix2, true);

            CollectionAssert.AreEqual(matrixRes, ints);
        }

        [TestMethod]
        public void TestAddWrong()
        {
            double[,] matrix1 = { { 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 } };
            double[,] matrix2 = { { 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 } };
            double[,] ints = matrix1.Add(matrix2);

            double[,] matrixRes = { { 3, 2, 2 }, { 4, 4, 4 }, { 6, 6, 6 } };

            CollectionAssert.AreNotEqual(matrixRes, ints);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void TestAddWrondDimensionSizes()
        {
            double[,] matrix1 = { { 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 }, { 3, 3, 3 } };
            double[,] matrix2 = { { 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 } };
            double[,] ints = matrix1.Add(matrix2);

            double[,] matrixRes = { { 2, 2, 2 }, { 4, 4, 4 }, { 6, 6, 6 } };

            CollectionAssert.AreEqual(matrixRes, ints);
            
        }


        [TestMethod]
        public void TestConvertIndexIntoArrayDimensionsNormal()
        {
            double[,] matrix1 = new double[5, 5];
            const long number = 10;
            long d1=0;
            long d2=0;
            bool convertIndexIntoArrayDimensions = matrix1.ConvertIndexIntoArrayDimensions(number, ref d1, ref d2);
            Assert.AreEqual(2, d1);
            Assert.AreEqual(0, d2);
            Assert.AreEqual(convertIndexIntoArrayDimensions, true);
        }

        [TestMethod]
        public void TestConvertIndexIntoArrayDimensionsNormal2()
        {
            double[,] matrix1 = new double[5, 5];
            const long number = 0;
            long d1 = 0;
            long d2 = 0;
            bool convertIndexIntoArrayDimensions = matrix1.ConvertIndexIntoArrayDimensions(number, ref d1, ref d2);
            Assert.AreEqual(0, d1);
            Assert.AreEqual(0, d2);
            Assert.AreEqual(convertIndexIntoArrayDimensions, true);
        }

        [TestMethod]
        public void TestConvertIndexIntoArrayDimensionsNormal3()
        {
            double[,] matrix1 = new double[5, 5];
            const long number = 5;
            long d1 = 0;
            long d2 = 0;
            bool convertIndexIntoArrayDimensions = matrix1.ConvertIndexIntoArrayDimensions(number, ref d1, ref d2);
            Assert.AreEqual(1, d1);
            Assert.AreEqual(0, d2);
            Assert.AreEqual(convertIndexIntoArrayDimensions, true);
        }

        [TestMethod]
        public void TestConvertIndexIntoArrayDimensionsNormal4()
        {
            double[,] matrix1 = new double[3, 3];
            matrix1[1, 2] = 5;
            const long number = 5;
            long d1 = 0;
            long d2 = 0;
            bool convertIndexIntoArrayDimensions = matrix1.ConvertIndexIntoArrayDimensions(number, ref d1, ref d2);
            Assert.AreEqual(1, d1);
            Assert.AreEqual(2, d2);
            Assert.AreEqual(convertIndexIntoArrayDimensions, true);
            Assert.AreEqual(5, matrix1[d1,d2]);
        }

        [TestMethod]
        public void TestConvertIndexIntoArrayDimensionsNormal5()
        {
            double[,] matrix1 = new double[1, 10];
            matrix1[0, 5] = 5;
            const long number = 5;
            long d1 = 0;
            long d2 = 0;
            bool convertIndexIntoArrayDimensions = matrix1.ConvertIndexIntoArrayDimensions(number, ref d1, ref d2);
            Assert.AreEqual(0, d1);
            Assert.AreEqual(5, d2);
            Assert.AreEqual(convertIndexIntoArrayDimensions, true);
            Assert.AreEqual(5, matrix1[d1, d2]);
        }

        [TestMethod]
        public void TestConvertIndexIntoArrayDimensionsWrong()
        {
            double[,] matrix1 = new double[5, 5];
            const long number = 50;
            long d1=0;
            long d2=0;
            bool convertIndexIntoArrayDimensions = matrix1.ConvertIndexIntoArrayDimensions(number, ref d1, ref d2);
            Assert.AreEqual(0, d1);
            Assert.AreEqual(0, d2);
            Assert.AreEqual(convertIndexIntoArrayDimensions, false);
        }

        [TestMethod]
        public void TestGenerate1DMatrix()
        {
            double[] generateRandom1DArray = MatrixOperations1D.GenerateRandom1DArray(50,5,20);
            Assert.AreEqual(50,generateRandom1DArray.Length);
            generateRandom1DArray.AllItemsAreInRange(5,20);

        }

        [TestMethod]
        public void TestDoubleByANumberNormal()
        {
            double[] generateRandom1DArray = MatrixOperations1D.GenerateRandom1DArray(50, 5, 20);
            double[] doubleByANumberActual = generateRandom1DArray.DoubleByANumberOneThread(5);
            double[] doubleByANumberExpected = generateRandom1DArray.DoubleByANumber(5);
            
            CollectionAssert.AreEqual(doubleByANumberExpected,doubleByANumberActual);
        }

        [TestMethod]
        public void TestDouble2DbyANumber()
        {
            double[,] matrix = MatrixOperations2D.GenerateRandom2DMatrix(500, 500);
            double[,] expected = matrix.Double2DbyANumberOneThread(10);
            double[,] actual = matrix.Double2DbyANumber(10);

            CollectionAssert.AreEqual(expected,actual);
        }


        [TestMethod]
        public void TestAddANumber()
        {
            double[] generateRandom1DArray = MatrixOperations1D.GenerateRandom1DArray(50, 5, 20);
            double[] doubleByANumberActual = generateRandom1DArray.DoubleByANumberOneThread(5);
            double[] doubleByANumberExpected = generateRandom1DArray.DoubleByANumber(5);

            CollectionAssert.AreEqual(doubleByANumberExpected, doubleByANumberActual);
        }

        [TestMethod]
        public void TestAdd2DANumber()
        {
            double[,] matrix = MatrixOperations2D.GenerateRandom2DMatrix(500, 500);
            double[,] expected = matrix.AddANumberOneThread(10);
            double[,] actual = matrix.AddANumber(10);

            CollectionAssert.AreEqual(expected, actual);
        }


    }
}
